package com.ecommerce.order.service.impl;

import com.ecommerce.common.core.PageResult;
import com.ecommerce.common.core.ApiResult;
import com.ecommerce.common.exception.BusinessException;
import com.ecommerce.order.dto.*;
import com.ecommerce.order.entity.Order;
import com.ecommerce.order.entity.OrderItem;
import com.ecommerce.order.entity.OrderStatus;
import com.ecommerce.product.dto.ProductInfo;
import com.ecommerce.order.events.OrderCreatedEvent;
import com.ecommerce.order.events.OrderTimeoutEvent;
import com.ecommerce.product.service.ProductService;
import com.ecommerce.order.repository.OrderItemRepository;
import com.ecommerce.order.repository.OrderRepository;
import com.ecommerce.order.service.OrderService;
import com.ecommerce.order.service.InventoryService;
import com.ecommerce.order.service.CouponService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
// import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private OrderItemRepository orderItemRepository;

    @Autowired
    private ProductService productService;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    //
    // @Autowired
    // private RedisTemplate<String, Object> redisTemplate;

    private static final String ORDER_NO_PREFIX = "ORD";
    private static final String ORDER_CACHE_PREFIX = "order:";

    @Override
    public ApiResult<OrderResponse> createOrder(Long userId, CreateOrderRequest request) {
        log.info("创建订单请求: userId={}, items={}", userId, request.getItems().size());

        try {
            // 1. 验证商品信息和库存
            List<ProductInfo> products = validateAndGetProducts(request.getItems());

            // 2. 计算订单金额
            OrderCalculation calculation = calculateOrderAmount(products, request.getItems(), request.getCouponId());

            // 3. 预扣库存
            boolean inventoryReserved = reserveInventory(request.getItems());
            if (!inventoryReserved) {
                return ApiResult.error("库存不足，下单失败");
            }

            try {
                // 4. 创建订单
                Order order = createOrderEntity(userId, request, calculation);
                order = orderRepository.save(order);

                // 5. 创建订单项
                List<OrderItem> orderItems = createOrderItems(order.getId(), products, request.getItems());
                orderItemRepository.saveAll(orderItems);

                // 6. 使用优惠券
                if (request.getCouponId() != null) {
                    couponService.useCoupon(userId, request.getCouponId(), order.getId());
                }

                // 7. 发送订单创建事件
                publishOrderCreatedEvent(order);

                // 8. 设置订单超时取消
                scheduleOrderTimeout(order.getOrderNo());

                log.info("订单创建成功: orderId={}, orderNo={}", order.getId(), order.getOrderNo());

                OrderResponse response = OrderResponse.fromOrder(order, orderItems);
                return ApiResult.success("订单创建成功", response);

            } catch (Exception e) {
                // 回滚库存预扣
                rollbackInventoryReservation(request.getItems());
                throw e;
            }

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建订单失败: userId={}, error={}", userId, e.getMessage(), e);
            throw new BusinessException("创建订单失败，请稍后重试");
        }
    }

    @Override
    public ApiResult<OrderResponse> getOrderDetail(Long userId, Long orderId) {
        // 查询订单
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("订单不存在"));

        // 验证订单所属用户
        if (!order.getUserId().equals(userId)) {
            throw new BusinessException("无权访问该订单");
        }

        // 查询订单项
        List<OrderItem> orderItems = orderItemRepository.findByOrderId(orderId);

        // 转换为响应对象
        OrderResponse response = OrderResponse.fromOrder(order, orderItems);
        return ApiResult.success(response);
    }

    @Override
    public ApiResult<PageResult<OrderResponse>> pageUserOrders(Long userId, OrderQueryRequest request) {
        // 构造分页参数
        Pageable pageable = PageRequest.of(request.getPageNum() - 1, request.getPageSize());
        
        // 转换订单状态
        OrderStatus status = null;
        if (request.getStatus() != null) {
            status = OrderStatus.fromCode(request.getStatus());
        }
        
        // 分页查询订单
        Page<Order> orderPage = orderRepository.findByUserIdAndStatus(userId, status, pageable);
        
        // 转换为响应对象列表
        List<OrderResponse> orderResponses = orderPage.getContent().stream()
                .map(order -> {
                    // 查询订单项
                    List<OrderItem> orderItems = orderItemRepository.findByOrderId(order.getId());
                    return OrderResponse.fromOrder(order, orderItems);
                })
                .collect(Collectors.toList());
        
        // 构造分页结果
        PageResult<OrderResponse> pageResult = PageResult.<OrderResponse>builder()
                .pageNum(request.getPageNum())
                .pageSize(request.getPageSize())
                .total(orderPage.getTotalElements())
                .list(orderResponses)
                .totalPage(orderPage.getTotalPages())
                .hasNextPage(orderPage.hasNext())
                .hasPreviousPage(orderPage.hasPrevious())
                .build();
        
        return ApiResult.success(pageResult);
    }

    @Override
    public ApiResult<Void> cancelOrder(Long userId, Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("订单不存在"));

        if (!order.getUserId().equals(userId)) {
            throw new BusinessException("无权取消该订单");
        }

        if (order.getStatus() != OrderStatus.PENDING_PAYMENT && order.getStatus() != OrderStatus.PAID) {
            throw new BusinessException("当前订单状态不允许取消");
        }

        // 更新订单状态
        order.setStatus(OrderStatus.CANCELLED);
        orderRepository.save(order);

        // 恢复库存
        List<OrderItem> items = orderItemRepository.findByOrderId(orderId);
        for (OrderItem item : items) {
            inventoryService.releaseInventory(item.getProductId(), item.getQuantity());
        }

        log.info("订单取消成功: orderId={}, userId={}", orderId, userId);
        return ApiResult.success(null);
    }

    @Override
    public ApiResult<Void> confirmReceive(Long userId, Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("订单不存在"));

        if (!order.getUserId().equals(userId)) {
            throw new BusinessException("无权操作该订单");
        }

        if (order.getStatus() != OrderStatus.SHIPPED) {
            throw new BusinessException("当前订单状态不允许确认收货");
        }

        order.setStatus(OrderStatus.COMPLETED);
        orderRepository.save(order);

        log.info("订单确认收货成功: orderId={}, userId={}", orderId, userId);
        return ApiResult.success(null);
    }

    @Override
    public ApiResult<Void> paymentSuccess(String orderNo, String paymentNo) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));

        if (order.getStatus() != OrderStatus.PENDING_PAYMENT) {
            throw new BusinessException("订单状态异常");
        }

        order.setStatus(OrderStatus.PAID);
        order.setPaymentNo(paymentNo);
        orderRepository.save(order);

        log.info("订单支付成功: orderNo={}, paymentNo={}", orderNo, paymentNo);
        return ApiResult.success(null);
    }

    @Override
    public ApiResult<Void> shipOrder(Long orderId, String trackingNo) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("订单不存在"));

        if (order.getStatus() != OrderStatus.PAID) {
            throw new BusinessException("订单状态异常");
        }

        order.setStatus(OrderStatus.SHIPPED);
        order.setTrackingNo(trackingNo);
        orderRepository.save(order);

        log.info("订单发货成功: orderId={}, trackingNo={}", orderId, trackingNo);
        return ApiResult.success(null);
    }

    @Override
    public OrderInfo getOrderByNo(String orderNo) {
        return orderRepository.findByOrderNo(orderNo)
                .map(order -> {
                    List<OrderItem> items = orderItemRepository.findByOrderId(order.getId());
                    return OrderInfo.fromOrder(order, items);
                })
                .orElse(null);
    }

    /**
     * 验证商品信息并获取商品详情
     */
    private List<ProductInfo> validateAndGetProducts(List<OrderItemRequest> items) {
        List<Long> productIds = items.stream()
                .map(OrderItemRequest::getProductId)
                .collect(Collectors.toList());

        List<ProductInfo> products = productService.getProductsByIds(productIds);

        if (products.size() != productIds.size()) {
            throw new BusinessException("部分商品不存在或已下架");
        }

        // 验证商品状态
        for (ProductInfo product : products) {
            if (product.getStatus() != 1) {
                throw new BusinessException("商品【" + product.getName() + "】已下架");
            }
        }

        return products;
    }

    /**
     * 计算订单金额
     */
    private OrderCalculation calculateOrderAmount(List<ProductInfo> products,
                                                List<OrderItemRequest> items,
                                                Long couponId) {
        Map<Long, ProductInfo> productMap = products.stream()
                .collect(Collectors.toMap(ProductInfo::getId, Function.identity()));

        long totalAmount = 0;
        for (OrderItemRequest item : items) {
            ProductInfo product = productMap.get(item.getProductId());
            totalAmount += product.getPrice() * item.getQuantity();
        }

        // 计算运费
        long shippingFee = calculateShippingFee(totalAmount);

        // 计算优惠金额
        long discountAmount = 0;
        if (couponId != null) {
            discountAmount = couponService.calculateDiscount(couponId, totalAmount);
        }

        long payAmount = totalAmount + shippingFee - discountAmount;

        return new OrderCalculation(totalAmount, payAmount, discountAmount, shippingFee);
    }

    /**
     * 计算运费
     */
    private long calculateShippingFee(long totalAmount) {
        // 满99元免运费
        return totalAmount >= 9900 ? 0 : 800; // 8元运费
    }

    /**
     * 创建订单项
     */
    private List<OrderItem> createOrderItems(Long orderId, List<ProductInfo> products, List<OrderItemRequest> items) {
        Map<Long, ProductInfo> productMap = products.stream()
                .collect(Collectors.toMap(ProductInfo::getId, Function.identity()));

        return items.stream()
                .map(item -> {
                    ProductInfo product = productMap.get(item.getProductId());
                    long subtotal = product.getPrice() * item.getQuantity();
                    
                    return OrderItem.builder()
                            .orderId(orderId)
                            .productId(product.getId())
                            .productName(product.getName())
                            .productPrice(product.getPrice())
                            .quantity(item.getQuantity())
                            .subtotal(subtotal)
                            .build();
                })
                .collect(Collectors.toList());
    }

    /**
     * 预扣库存
     */
    private boolean reserveInventory(List<OrderItemRequest> items) {
        for (OrderItemRequest item : items) {
            boolean reserved = inventoryService.reserveInventory(item.getProductId(), item.getQuantity());
            if (!reserved) {
                // 回滚已预扣的库存
                rollbackInventoryReservation(items.subList(0, items.indexOf(item)));
                return false;
            }
        }
        return true;
    }

    /**
     * 回滚库存预扣
     */
    private void rollbackInventoryReservation(List<OrderItemRequest> items) {
        for (OrderItemRequest item : items) {
            inventoryService.releaseReservedInventory(item.getProductId(), item.getQuantity());
        }
    }

    /**
     * 创建订单实体
     */
    private Order createOrderEntity(Long userId, CreateOrderRequest request, OrderCalculation calculation) {
        String orderNo = generateOrderNo();

        return Order.builder()
                .orderNo(orderNo)
                .userId(userId)
                .status(OrderStatus.PENDING_PAYMENT)
                .totalAmount(calculation.getTotalAmount())
                .payAmount(calculation.getPayAmount())
                .discountAmount(calculation.getDiscountAmount())
                .shippingFee(calculation.getShippingFee())
                .receiverName(request.getReceiverName())
                .receiverPhone(request.getReceiverPhone())
                .receiverAddress(request.getReceiverAddress())
                .remark(request.getRemark())
                .build();
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String random = String.format("%04d", new Random().nextInt(10000));
        return ORDER_NO_PREFIX + timestamp + random;
    }

    /**
     * 发布订单创建事件
     */
    private void publishOrderCreatedEvent(Order order) {
        try {
            OrderCreatedEvent event = new OrderCreatedEvent(order.getId(), order.getOrderNo(),
                                                           order.getUserId(), order.getCreateTime());
            rabbitTemplate.convertAndSend("order.exchange", "order.created", event);
        } catch (Exception e) {
            log.warn("发送订单创建事件失败: orderId={}, error={}", order.getId(), e.getMessage());
        }
    }

    /**
     * 设置订单超时取消
     */
    private void scheduleOrderTimeout(String orderNo) {
        try {
            // 30分钟后自动取消未支付订单
            OrderTimeoutEvent event = new OrderTimeoutEvent(orderNo);
            rabbitTemplate.convertAndSend("order.exchange", "order.timeout", event,
                message -> {
                    message.getMessageProperties().setExpiration("1800000"); // 30分钟延迟(毫秒)
                    return message;
                });
        } catch (Exception e) {
            log.warn("设置订单超时失败: orderNo={}, error={}", orderNo, e.getMessage());
        }
    }
}